#!/usr/bin/python
# -*- coding: utf-8 -*-
import json
import os
import sys
import time
import uuid
import warnings
from multiprocessing import Process
from os.path import join
import sumolib
import shapely.geometry as geo
import traci
from flask import request


import rou
import rou.constants as rc
import scene
import sumo_main
import sumo_utils
from fileUtil import FileUtil
from httpserver.json_flask import JsonFlask
from httpserver.json_response import JsonResponse
from rou._config_item import ConfigItem
from utils import construction_area_util
from utils.net_util import create_sumocfg, download_file

# app = Flask(__name__)
app = JsonFlask(__name__)
# 添加车辆数
platoon = 0
vehicleNum = 0
vehiclePoints = None
# 场景区域
areaPoints = list()
eventType = 0
# 限速区域配置
speeds = []
speedLimitPoints = []

# 交通灯
trafficLight = []
# 事故区
accident = list()
accidentControl = None
accidentResponse = None
# 主路限速场景应急车道
emergencyLaneConfig = None
emergencyLaneSwitch = {}
emergencyLaneControl = None
# 主路限速场景专用车道
exclusiveLaneConfig = None
exclusiveLaneSwitch = {}
exclusiveLaneControl = None
# sumo仿真状态
status = None
# 匝道默认理论值为每分钟7辆
rampControlNum = 7
# 门架位置
gantry_list = list()
gantry_file = './scene/gantry/gantry_init.json'

bad_weather_config = None
del_bad_weather_param = None

PENDING = 'pending'
SUCCESS = 'success'
ERROR = 'error'


@app.route('/getGantryList', methods=['Get'])
def getGantryList():
    """
    获取门架列表
    :return:
    """
    return JsonResponse.success(gantry_list)


@app.route('/setGantryList', methods=['Post'])
def setGatryList():
    """
    设置门架
    :return:
    """
    global gantry_list
    temp_dict = request.get_json()
    print("param:", temp_dict)
    assert type(temp_dict).__name__ == 'dict', '参数异常'
    code, message = updateAndCheckGantry(temp_dict)
    return JsonResponse.error(message) if code == 500 else JsonResponse.success('设置完成')


def updateAndCheckGantry(param: dict):
    """
    更新并检查门架列表
    :param param:
    :return:
    """
    global gantry_list
    temp_gantry_list = gantry_list
    if 'id' in param:
        if param['id'] not in [item['id'] for item in temp_gantry_list]:
            return 500, '门架不存在'
        temp_gantry_list = list(map(lambda x: param if x['id'] == param['id'] else x, temp_gantry_list))
    else:
        param['id'] = uuid.uuid4()
        temp_gantry_list.append(param)
    if len(areaPoints) > 0:
        polygon = geo.Polygon(areaPoints)
        temp_gantry_list = list(map(lambda x: updateGantryItem(x, True, False) if polygon.contains(
            geo.Point(x['point'][0], x['point'][1])) else updateGantryItem(x), temp_gantry_list))
        in_limit_gantry = [item for item in temp_gantry_list if item['inLimitArea']]
        # in_limit_gantry = list(filter(lambda x: x['inLimitArea'], temp_gantry_list))
        in_limit_points = [item['point'] for item in in_limit_gantry]
        lon, lat = sumo_utils.center_geolocation(in_limit_points)
        nearest_item = getNearestGantry(in_limit_gantry, lon, lat)
        gantry_list = list(
            map(lambda x: updateGantryItem(x, True, True) if x['id'] == nearest_item['id'] else x, temp_gantry_list))
    else:
        gantry_list = list(map(lambda x: updateGantryItem(x), temp_gantry_list))
    return 200, '设置完成'


def getNearestGantry(temp_gantry_list: list, lon, lat):
    """
    获取距离某点最近的门架
    :param temp_gantry_list: 门架集合
    :param lon: 经度
    :param lat: 纬度
    :return: 最近的门架
    """
    dist = sys.maxsize
    nearest_item = {}
    for item in temp_gantry_list:
        temp_dist = sumo_utils.calculate_distance(lon, lat, item['point'][1], item['point'][0])
        if temp_dist < dist:
            dist = temp_dist
            nearest_item = item
    return nearest_item


def updateGantryItem(x, inLimitArea=False, couldSetBW=True, bad_weather=None):
    """
    更新门架元素
    :param x: 门架信息
    :param inLimitArea: 是否处于主路限速区域
    :param couldSetBW: 是否允许设置恶劣天气
    :param bad_weather: 恶劣天气信息
    :return: 门架信息
    """
    x['inLimitArea'] = inLimitArea
    x['couldSetBW'] = couldSetBW
    if couldSetBW:
        if bad_weather is not None:
            x['bwInfo'] = {'radius': bad_weather['radius']}
    else:
        x['bwInfo'] = None
    return x


@app.route('/setBadWeather', methods=['Post'])
def setBadWeather():
    """
    设置恶劣天气
    :return:
    """
    global gantry_list, bad_weather_polygon, bad_weather_config
    temp_dict = request.get_json()
    print("param:", temp_dict)
    assert len(gantry_list) > 0, '请先设置门架'
    assert type(temp_dict).__name__ == 'dict', '参数异常'
    assert 'lon' in temp_dict and 'lat' in temp_dict, '请确认恶劣天气区域中心经纬度'
    assert 'radius' in temp_dict, '请确认恶劣天气区域半径'

    temp_gantry_list = gantry_list
    could_set_gantry = [item for item in temp_gantry_list if item['couldSetBW']]
    nearest_item = getNearestGantry(could_set_gantry, temp_dict['lon'], temp_dict['lat'])
    gantry_list = list(
        map(lambda x: updateGantryItem(x, x['inLimitArea'], True, temp_dict) if x['id'] == nearest_item['id'] else x,
            gantry_list))
    bad_weather_config = {'id': nearest_item['id'], 'point': (nearest_item['point'][0], nearest_item['point'][1]),
                          'radius': int(temp_dict['radius'] + 10), 'speedLimit': nearest_item['speedLimit']}
    return JsonResponse.success(gantry_list)


@app.route('/delBadWeather', methods=['Get'])
def delBadWeather():
    """
    删除恶劣天气
    :return:
    """
    global gantry_list, del_bad_weather_param
    gantry_id = int(request.args.get('id'))
    print("param:", gantry_id)
    assert gantry_id, '请选择恶劣天气区域'
    temp_gantry_list = gantry_list
    if gantry_id not in [item['id'] for item in temp_gantry_list]:
        return JsonResponse.error('门架不存在')

    temp_gantry_list = gantry_list
    gantry_list = list(
        map(lambda x: updateGantryItem(x, x['inLimitArea'], False) if x['id'] == gantry_id else x, temp_gantry_list))
    del_bad_weather_param = gantry_id
    return JsonResponse.success(gantry_list)


# 添加车辆配置
@app.route('/addVehicle', methods=['GET'])
def addVehicle():
    global vehicleNum, vehiclePoints, platoon
    platoon = int(request.args.get('platoon'))
    vehicleNum = int(request.args.get('vehicleNum'))
    vehiclePoints = request.args.get('vehiclePoints')
    return 'Hello, {}{}!'.format(vehicleNum, vehiclePoints)


# 场景区域配置
@app.route('/accidentAreaScenarioConfig', methods=['POST'])
def accidentAreaScenarioConfig():
    global areaPoints, eventType, gantry_list

    areaPoints_str = request.form['areaPoints']
    areaPointsobjs = json.loads(areaPoints_str)
    for areaPointsobj in areaPointsobjs:
        areaPoints.append((areaPointsobj['lat'], areaPointsobj['lon']))
    if len(gantry_list) < 1:
        with open(gantry_file, 'r') as f:
            gantry_list = json.loads(f.read())
    eventType = request.form['eventType']
    return 'Hello, {}{}!'.format(areaPoints, eventType)


# 限速区域配置
@app.route('/speedLimitConfig', methods=['POST'])
def speedLimitConfig():
    global speedLimitPoints, speeds
    speedLimitPoints_str = request.form['speedLimitPoints']
    speeds_str = request.form['speeds']
    speedLimitPoints = json.loads(speedLimitPoints_str)
    speeds = json.loads(speeds_str)
    return 'Hello, {}{}!'.format(speedLimitPoints, speeds)


# 红绿灯配置
@app.route('/trafficLightConfig', methods=['Get'])
def trafficLightConfig():
    global trafficLight
    trafficLight = int(request.args.get('trafficLight'))
    return 'Hello, {}!'.format(trafficLight)


# 事故区配置
@app.route('/addAccidentArea', methods=['Post'])
def addAccidentArea():
    global accident, accidentResponse
    temp_list = request.get_json()
    assert type(temp_list).__name__ == 'list' and len(temp_list) == 4, '请选择两个点位确认事故区'
    try:
        temp_param = list()
        for point in temp_list:
            temp_param.append((point['lat'], point['lon']))
        accidentResponse = PENDING
        accident = temp_param
        s_time = time.time()
        while accidentResponse == PENDING:
            print('事故区添加中')
        print('事故区添加耗时：', time.time() - s_time)
        return accidentResponse
    finally:
        accidentResponse = None


@app.route('/controlAccidentArea', methods=['Post'])
def controlAccidentArea():
    """
    控制事故区
    :return:
    """
    temp = request.get_json()
    assert 'switch' in temp and int(temp['switch']) == -1 or int(temp['switch']) == 0 or int(
        temp['switch']) == 1, '请选择正确控制方式'
    assert 'accidentId' in temp and temp['accidentId'], '请选择事故区'
    global accidentControl, accidentResponse
    try:
        accidentResponse = PENDING
        accidentControl = temp
        s_time = time.time()
        while accidentResponse == PENDING:
            print('事故区更新中')
        print('事故区更新耗时：', time.time() - s_time)
        return accidentResponse
    finally:
        accidentResponse = None


@app.route('/getAccidentArea', methods=['Get'])
def getAccidentArea():
    accident_id = request.args.get('accidentId')
    if accident_id:
        area = scene.accident.get_accident_polygon(accident_id)
        return JsonResponse.success(area.to_dict() if area else {})
    return JsonResponse.success(scene.accident.get_accident_polygon_list())


# 增加应急车道配置
# {
# 	"coordinate":[]
# }
@app.route('/addEmergencyLaneConfig', methods=['Post'])
def addEmergencyLaneConfig():
    global emergencyLaneConfig
    temp = request.get_json()
    assert type(temp).__name__ == 'list' and len(temp) == 2, '请选择两个点位确认应急车道'
    emergencyLaneConfig = request.get_json()
    return JsonResponse.success_with_msg('应急车道配置完成')


@app.route('/actionEmergencyLane', methods=['Post'])
def actionEmergencyLane():
    global emergencyLaneControl
    temp = request.get_json()
    switch = temp['switch']
    assert switch == -1 or switch == 0 or switch == 1, '请选择正确控制方式'
    point = temp['point']
    assert type(point).__name__ == 'dict', '请选择应急车道'
    emergencyLaneControl = temp
    return JsonResponse.success_with_msg('操作成功')


@app.route('/addExclusiveLaneConfig', methods=['Post'])
def addExclusiveLaneConfig():
    global exclusiveLaneConfig
    temp = request.get_json()
    assert type(temp).__name__ == 'list' and len(temp) == 2, '请选择两个点位确认专用车道'
    exclusiveLaneConfig = request.get_json()
    return JsonResponse.success_with_msg('专用车道配置添加完成')


@app.route('/actionExclusiveLane', methods=['Post'])
def actionExclusiveLane():
    global exclusiveLaneControl
    temp = request.get_json()
    switch = temp['switch']
    assert switch == -1 or switch == 0 or switch == 1, '请选择正确控制方式'
    point = temp['point']
    assert type(point).__name__ == 'dict', '请选择专用车道'
    exclusiveLaneControl = temp
    return JsonResponse.success_with_msg('操作成功')


process_dist = {}


@app.route('/startOrStop', methods=['Post'])
def startOrStop():
    warnings.warn("此方法已废弃，不推荐使用", DeprecationWarning)
    global status, process_dist
    # 0开启1关闭
    temp = request.get_json()

    task_id = temp['taskId']
    status = temp['status']

    topicType = temp['topicType']
    default_path = rc.DEFAULT_PATH
    sumo_net_file = join(default_path, "6e2fccc4-f09d-411e-93ba-407b6f70c0f9.net.xml")  # 路网文件
    sumo_cfg_file = join(default_path, "长安大学_openDrive_v0.sumocfg")  # 路网文件
    config_name_map = rou.config.get_config_name_map()
    # print(config_name_map)
    if task_id not in config_name_map.keys():
        return JsonResponse.error('启动失败，未配置路由')
    task_cfg = config_name_map[task_id]
    if topicType == 'webgl':
        if status == '0':
            sumo_process = Process(target=sumo_main.main1,
                                   args=(task_cfg, sumo_cfg_file, sumo_net_file, True, topicType))
            process_dist['webgl'] = sumo_process
            if not process_dist['webgl'].is_alive():
                sumo_process.start()
            return JsonResponse.success('启动完成')
        elif status == '1' and len(process_dist) > 0:
            try:

                task_process = process_dist.get('webgl')
                process_dist.pop('webgl')
                # if task_process is not No ne and task_process.is_alive():
                task_process.terminate()
                task_process.close()

            except Exception as e:
                return JsonResponse.success('关闭仿真')
        elif len(process_dist) > 0:
            return JsonResponse.success('程序已经开启')

    elif topicType == 'ls':
        if status == '0':
            sumo_process = Process(target=sumo_main.main1,
                                   args=(task_cfg, sumo_cfg_file, sumo_net_file, True, topicType))
            process_dist['ls'] = sumo_process
            if not process_dist['ls'].is_alive():
                sumo_process.start()
            return JsonResponse.success('启动完成')
        elif status == '1' and len(process_dist) > 0:
            try:
                task_process = process_dist.get('ls')
                process_dist.pop('ls')
                task_process.terminate()
                task_process.close()
            except Exception as e:
                return JsonResponse.success('关闭仿真')
        elif len(process_dist) > 0:
            return JsonResponse.success('程序已经开启')


@app.route('/startSumo', methods=['Post'])
def startSumo():
    '''
        启动仿真
    '''
    global process_dist
    rou_cfg = request.get_json()
    # 参数检验
    assert 'taskId' in rou_cfg.keys(), '任务id不能为空'
    assert 'userId' in rou_cfg.keys(), '用户id不能为空'
    assert 'name' in rou_cfg.keys(), '路由名称不能为空'
    assert 'rouUrl' in rou_cfg.keys(), '路由位置不能为空'
    assert 'source' in rou_cfg.keys(), '来源不能为空'
    assert 'type' in rou_cfg.keys(), '路由模式不能为空'
    # 首先创建 sumocfg 文件
    taskId = rou_cfg['taskId']
    userId = rou_cfg['userId']
    name = rou_cfg['name']
    source = rou_cfg['source']
    # net_path = rou_cfg['netPath']
    rouUrl = rou_cfg['rouUrl']
    simulationStatus = rou_cfg['simulationStatus']
    default_path = rc.DEFAULT_PATH
    sumo_key = str(userId) + '_' + str(taskId) + '_' + str(source)
    sumo_rou_file = join(default_path, sumo_key + rc.ROU_SUFFIX)
    sumo_rou_file = download_file(rouUrl, sumo_rou_file)
    sumo_net_file = join(default_path, "6e2fccc4-f09d-411e-93ba-407b6f70c0f9.net.xml")  # 路网文件
    sumo_cfg_file = create_sumocfg(sumo_net_file, sumo_rou_file, userId, taskId, source)
    # 首先判断仿真是否已经启动
    if sumo_key in process_dist.keys():
        if process_dist[sumo_key].is_alive():
            return JsonResponse.success('程序已经启动')
        else:
            process_dist.pop(sumo_key)
    # 启动仿真
    if simulationStatus==0:
        sumo_process = Process(target=sumo_main.main1,
                           args=(userId, taskId, rou_cfg, sumo_cfg_file, sumo_net_file, True, source))
    elif simulationStatus==1:
        sumo_process = Process(target=sumo_main.main2,
                               args=(userId, taskId, rou_cfg, sumo_cfg_file, sumo_net_file, True, source))

    process_dist[sumo_key] = sumo_process
    sumo_process.start()
    return JsonResponse.success('启动完成')

@app.route('/MTFstartSumo', methods=['Post'])
def MTFstartSumo():
    '''
        启动仿真
    '''
    global process_dist
    rou_cfg = request.get_json()
    # 参数检验
    assert 'taskId' in rou_cfg.keys(), '任务id不能为空'
    assert 'userId' in rou_cfg.keys(), '用户id不能为空'
    assert 'name' in rou_cfg.keys(), '路由名称不能为空'
    assert 'rouUrl' in rou_cfg.keys(), '路由位置不能为空'
    assert 'source' in rou_cfg.keys(), '来源不能为空'
    assert 'MTFType' in rou_cfg.keys(), '仿真类型不能为空'

    print("前端请求内容为", rou_cfg)
    # 首先创建 sumocfg 文件
    taskId = rou_cfg['taskId']
    userId = rou_cfg['userId']
    name = rou_cfg['name']
    source = rou_cfg['source']
    # net_path = rou_cfg['netPath']
    rouUrl = rou_cfg['rouUrl']
    MTFType = rou_cfg['MTFType']
    default_path = rc.DEFAULT_PATH
    sumo_key = str(userId) + '_' + str(taskId) + '_' + str(source)
    # sumo_rou_file = join(default_path, sumo_key + rc.ROU_SUFFIX)
    # sumo_rou_file = download_file(rouUrl, sumo_rou_file)
    if MTFType == "0":
        sumo_rou_file = r"zhuluxiansu.rou.xml"
    if MTFType == "1":
        sumo_rou_file = r"zadaoguankong.rou.xml"
    sumo_net_file = join(default_path, "changandaxue.net.xml")  # 路网文件
    sumo_cfg_file = create_sumocfg(sumo_net_file, sumo_rou_file, userId, taskId, source)
    print("路由文件为",sumo_rou_file)
    print("路网文件为",sumo_net_file)
    print("配置文件为",sumo_cfg_file)
    # sumo_rou_file = r"D:\工作\项目\长安大学\项目\新需求\CADXWCFZ_sumo\webgl\test_39_0.rou.xml"
    # sumo_net_file = r"D:\工作\项目\长安大学\项目\新需求\CADXWCFZ_sumo\webgl\changandaxue.net.xml"
    # sumo_cfg_file = r"D:\工作\项目\长安大学\项目\新需求\CADXWCFZ_sumo\webgl\test_39_0.sumocfg"
    # 首先判断仿真是否已经启动
    if sumo_key in process_dist.keys():
        if process_dist[sumo_key].is_alive():
            return JsonResponse.success('程序已经启动')
        else:
            process_dist.pop(sumo_key)
    print(MTFType,"仿真状态")
    # 启动仿真
    if MTFType == "0":
        sumo_process = Process(target=sumo_main.main3,
                               args=(userId, taskId, rou_cfg, sumo_cfg_file, sumo_net_file, True, source))
    if MTFType == "1":
        sumo_process = Process(target=sumo_main.main3,
                               args=(userId, taskId, rou_cfg, sumo_cfg_file, sumo_net_file, True, source))

    process_dist[sumo_key] = sumo_process
    sumo_process.start()
    return JsonResponse.success('启动完成')














@app.route('/stopSumo', methods=['Post'])
def stopSumo():
    '''
        结束仿真
    '''
    global process_dist
    rou_cfg = request.get_json()
    # 参数检验
    assert 'taskId' in rou_cfg.keys(), '任务id不能为空'
    assert 'userId' in rou_cfg.keys(), '用户id不能为空'
    assert 'source' in rou_cfg.keys(), '来源不能为空'
    # 首先创建 sumocfg 文件
    taskId = rou_cfg['taskId']
    userId = rou_cfg['userId']
    source = rou_cfg['source']
    # 首先判断仿真是否已经启动
    sumo_key = str(userId)+'_'+str(taskId)+'_' + str(source)
    if sumo_key in process_dist.keys():
        if process_dist[sumo_key].is_alive():
            sumo_main.depart_info = {}
            try:
                task_process = process_dist.get(sumo_key)
                process_dist.pop(sumo_key)
                task_process.terminate()
                task_process.join()
                task_process.close()
            except Exception as e:
                print(e)
            # # 删除文件
            # default_path = rc.DEFAULT_PATH
            # sumo_key = str(userId) + '_' + str(taskId) + '_' + str(source)
            # sumo_rou_file = join(default_path, sumo_key + rc.ROU_SUFFIX)
            # sumo_cfg_file = join(default_path, sumo_key + rc.CONFIG_SUFFIX)
            # if os.path.exists(sumo_rou_file):
            #     os.remove(sumo_rou_file)
            # if os.path.exists(sumo_cfg_file):
            #     os.remove(sumo_cfg_file)

            return JsonResponse.success('仿真已关闭')
        else:
            process_dist.pop(sumo_key)
            return JsonResponse.success('仿真已关闭')
    return JsonResponse.error('仿真关闭失败')


@app.route('/getRouList', methods=['Get'])
def getRouList():
    # 判断该任务id是否在文件里
    taskId = int(request.args.get('taskId'))

    my_list = rou.config.get_all_config()
    default_path = rc.DEFAULT_PATH
    FileUtil.check_and_write_file(join(default_path, str(taskId) + ".task"),
                                  json.dumps(my_list, ensure_ascii=False))
    file = open(join(default_path, str(taskId) + ".task"), "r", encoding="utf-8")
    # 读取文件内容
    content = file.read()
    return JsonResponse.success(json.loads(content))

@app.route('/getRouPointList', methods=['Post'])
def getRouPointList():
    temp = request.get_json()
    default_path = rc.DEFAULT_PATH
    sumo_rou_file = join(default_path, 'routingConversion' + rc.ROU_SUFFIX)
    rou_path_url = temp['rouPath']
    download_file(rou_path_url,sumo_rou_file)
    # net_path = temp['netPath']
    # rou_path = join(rc.DEFAULT_PATH, 'hello.rou1.xml')
    net_path = join(rc.DEFAULT_PATH, '6e2fccc4-f09d-411e-93ba-407b6f70c0f9.net.xml')
    return ConfigItem.get_routePoint(sumo_rou_file,net_path)
no = None


@app.route('/getRouteDetail', methods=['Get'])
def getRouteDetail():
    # 判断是哪个路由
    no = request.args.get('no')
    list = rou.config.get_all_config()
    routeDetail = None
    for route in list:
        if no in str(route['no']):
            file = open('../rou/roue.txt', 'w')
            routeDetail = route
            routeDetail_jsonstr = json.dumps(routeDetail)
            file.write(routeDetail_jsonstr)
    if routeDetail == None:
        with open('../rou/roue.txt', 'r') as file:
            routeDetail = file.readline()
            routeDetail = json.loads(routeDetail)

    return JsonResponse.success(routeDetail)


# 修改路由配置
@app.route('/updateRouConfig', methods=['Post'])
def updateRouConfig():
    temp = request.get_json()
    task_id = temp['tId']
    rou_id = temp['rouId']
    rou_config = temp['rouConfig']
    rou_operate = temp['operate']
    task = rou.config.update_config(task_id, rou_id, rou_config, rou_operate)
    # FileUtil.check_and_write_file_update('../webgl/' + str(task_id) + ".task", task)
    return JsonResponse.success(json.loads(task))


# 匝道管控
@app.route('/addRampControl', methods=['Get'])
def addRampControl():
    global rampControlNum
    # 0开启1关闭
    rampControlNum = int(request.args.get('rampControlNum'))
    # sumo_main.main1(status)
    return rampControlNum


# 上传路由文件接口
@app.route('/upload', methods=['POST'])
def upload_file():
    file = request.files['file']
    filename = request.form['filename']
    file.save(filename)
    return '文件已保存'
# 施工区特殊道路id
special_edge_ids=['-299.0.00','300.299','-300.0.00','-276.0.00.38','-277.0.00']
@app.route('/checkConfig', methods=['POST'])
def checkConfig():
    global special_edge_ids
    start1 = time.time()
    rou_cfg = request.get_json()

    # 参数检验
    assert 'taskId' in rou_cfg.keys(), '任务id不能为空'
    assert 'userId' in rou_cfg.keys(), '用户id不能为空'
    assert 'name' in rou_cfg.keys(), '路由名称不能为空'
    assert 'rouUrl' in rou_cfg.keys(), '路由位置不能为空'
    assert 'source' in rou_cfg.keys(), '来源不能为空'
    assert 'type' in rou_cfg.keys(), '路由模式不能为空'
    assert 'sceneInfo' in rou_cfg.keys(), '事件不能为空'
    # 首先创建 sumocfg 文件
    taskId = rou_cfg['taskId']
    userId = rou_cfg['userId']
    name = rou_cfg['name']
    source = rou_cfg['source']
    # net_path = rou_cfg['netPath']
    rouUrl = rou_cfg['rouUrl']
    sceneInfo = rou_cfg['sceneInfo']

    default_path = rc.DEFAULT_PATH
    sumo_key = str(userId) + '_' + str(taskId) + '_' + str(source)
    sumo_rou_file = join(default_path, sumo_key + rc.ROU_SUFFIX)
    sumo_rou_file = download_file(rouUrl, sumo_rou_file)
    sumo_net_file = join(default_path, "6e2fccc4-f09d-411e-93ba-407b6f70c0f9.net.xml")  # 路网文件
    sumo_cfg_file = create_sumocfg(sumo_net_file, sumo_rou_file, userId, taskId, source)
    # start_sumo(sumo_cfg_file, False, gui=False)

    traci.start(cmd=['sumo',
                     '-c', sumo_cfg_file,
                     '--step-length', str(0.1),
                     # '--lateral-resolution', '0.25',
                     '--collision.check-junctions',
                     # '--fcd-output', out_file,
                     # "--fcd-output.geo",
                     '--lanechange.duration', '1']
                )

    # 校验施工区是否在一个车道上
    accidents=sceneInfo['accident']
    # x,y=sumo_utils.latAndLonConversionXY(sumo_net,(lon, lat))
    for accident in accidents:

        areaPoints=accident['areaPoints']
        # for i in range(len(areaPoints)):
        try:
            edgeID_0, pos_0, laneIndex_0 = traci.simulation.convertRoad(areaPoints[0][0], areaPoints[0][1], True)
            edgeID_1, pos_1, laneIndex_1 = traci.simulation.convertRoad(areaPoints[-1][0], areaPoints[-1][1], True)
            if laneIndex_0 == laneIndex_1 or (edgeID_0 in special_edge_ids and edgeID_1 in special_edge_ids and laneIndex_0-2 == laneIndex_1):
                default_path = rc.DEFAULT_PATH
                sumo_net_path = join(default_path, "6e2fccc4-f09d-411e-93ba-407b6f70c0f9.net.xml")
                sumo_net = sumolib.net.readNet(sumo_net_path, withInternal=True, withLatestPrograms=True)

                # edge_lane = sumo_net.getLane(edgeID_0 + "_" + str(laneIndex_0))
                # edge_lane2 = sumo_net.getLane(edgeID_0 + "_" + str(2))
                # shapes = edge_lane.getShape()


                # raw_shapes2 = edge_lane2.getBoundingBox()
                # point = sumo_net.convertXY2LonLat(raw_shapes[0], raw_shapes[1])
                # point1 = sumo_net.convertXY2LonLat(raw_shapes[2], raw_shapes[3])
                polygons = list()
                if edgeID_0==edgeID_1:
                    if pos_0>pos_1:
                        areaPoints.reverse()
                    edge_lane = sumo_net.getLane(edgeID_0 + "_" + str(laneIndex_0))
                    # shapes = edge_lane.getShape()
                    width=edge_lane.getWidth()
                    raw_shapes = edge_lane.getBoundingBox(includeJunctions=False)
                    upper_left_point = sumo_net.convertXY2LonLat(raw_shapes[0], raw_shapes[1])
                    upper_right_point = sumo_net.convertXY2LonLat(raw_shapes[2], raw_shapes[3])
                    polygons=construction_area_util.construction_area_convert(upper_left_point,upper_right_point,width)
                    # for shape in shapes:
                    #     point = sumo_net.convertXY2LonLat(shape[0], shape[1])
                    #     point = [i for i in point]
                    #     print(point)  # Output: [1, 2]
                    #     polygons.append(point)
                    accident['polygons']=polygons
                else:
                    start_edge_lane = sumo_net.getLane(edgeID_0 + "_" + str(laneIndex_0))
                    end_edge_lane = sumo_net.getLane(edgeID_1 + "_" + str(laneIndex_1))
                    start_width = start_edge_lane.getWidth()
                    end_width = end_edge_lane.getWidth()
                    start_raw_shapes = start_edge_lane.getBoundingBox()
                    end_raw_shapes = end_edge_lane.getBoundingBox()
                    upper_left_point = sumo_net.convertXY2LonLat(start_raw_shapes[0], start_raw_shapes[1])
                    upper_right_point = sumo_net.convertXY2LonLat(end_raw_shapes[2], end_raw_shapes[3])
                    polygons = construction_area_util.construction_area_convert(upper_left_point, upper_right_point,
                                                                                start_width)
                    edgeID_0=edgeID_0[:edgeID_0.rfind('.')]
                    edgeID_1=edgeID_1[:edgeID_1.rfind('.')]
                    # edgeID_int_0=construction_area_util.edgeid_toInt(edgeID_0)
                    # edgeID_int_1=construction_area_util.edgeid_toInt(edgeID_1)
                    # if edgeID_int_0<edgeID_int_1:
                    #     areaPoints.reverse()
                    # start_shape = start_edge_lane.getShape()
                    #
                    # end_shape = end_edge_lane.getShape()
                    # # areaPoints.clear()
                    # for start_shape_i in start_shape:
                    #     start_point = sumo_net.convertXY2LonLat(start_shape_i[0], start_shape_i[1])
                    #     start_point = [i for i in start_point]
                    #     polygons.append(start_point)
                    # for end_shape_i in end_shape:
                    #     end_point = sumo_net.convertXY2LonLat(end_shape_i[0], end_shape_i[1])
                    #     end_point = [i for i in end_point]
                    #     polygons.append(end_point)
                    accident['polygons'] = polygons

            else:
                traci.close()
                return JsonResponse.accident_error('施工区未在一个车道上')
        except Exception as e:
            print(str(e))
            traci.close()
            return JsonResponse.accident_error('施工区没在地图上')
    traci.close()
    end1 = time.time()
    print(end1-start1)
    print(rou_cfg)
    return JsonResponse.success(rou_cfg)
@app.route('/checkConfig1', methods=['POST'])
def checkConfig1():
    global special_edge_ids
    start1 = time.time()
    rou_cfg = request.get_json()
    # 参数检验
    assert 'taskId' in rou_cfg.keys(), '任务id不能为空'
    assert 'userId' in rou_cfg.keys(), '用户id不能为空'
    assert 'name' in rou_cfg.keys(), '路由名称不能为空'
    assert 'rouUrl' in rou_cfg.keys(), '路由位置不能为空'
    assert 'source' in rou_cfg.keys(), '来源不能为空'
    assert 'type' in rou_cfg.keys(), '路由模式不能为空'
    assert 'sceneInfo' in rou_cfg.keys(), '事件不能为空'
    # 首先创建 sumocfg 文件
    taskId = rou_cfg['taskId']
    userId = rou_cfg['userId']
    name = rou_cfg['name']
    source = rou_cfg['source']
    # net_path = rou_cfg['netPath']
    rouUrl = rou_cfg['rouUrl']
    sceneInfo = rou_cfg['sceneInfo']

    default_path = rc.DEFAULT_PATH
    sumo_key = str(userId) + '_' + str(taskId) + '_' + str(source)
    sumo_rou_file = join(default_path, sumo_key + rc.ROU_SUFFIX)
    sumo_rou_file = download_file(rouUrl, sumo_rou_file)
    sumo_net_file = join(default_path, "6e2fccc4-f09d-411e-93ba-407b6f70c0f9.net.xml")  # 路网文件
    sumo_cfg_file = create_sumocfg(sumo_net_file, sumo_rou_file, userId, taskId, source)
    # start_sumo(sumo_cfg_file, False, gui=False)

    traci.start(cmd=['sumo',
                     '-c', sumo_cfg_file,
                     '--step-length', str(0.1),
                     # '--lateral-resolution', '0.25',
                     '--collision.check-junctions',
                     # '--fcd-output', out_file,
                     # "--fcd-output.geo",
                     '--lanechange.duration', '1']
                )

    # 校验施工区是否在一个车道上
    accidents=sceneInfo['accident']
    # x,y=sumo_utils.latAndLonConversionXY(sumo_net,(lon, lat))
    for accident in accidents:

        areaPoints=accident['areaPoints']
        # for i in range(len(areaPoints)):
        try:
            edgeID_0, pos_0, laneIndex_0 = traci.simulation.convertRoad(areaPoints[0][0], areaPoints[0][1], True)
            edgeID_1, pos_1, laneIndex_1 = traci.simulation.convertRoad(areaPoints[-1][0], areaPoints[-1][1], True)
            if laneIndex_0 == laneIndex_1 or (edgeID_0 in special_edge_ids and edgeID_1 in special_edge_ids and laneIndex_0-2 == laneIndex_1):
                default_path = rc.DEFAULT_PATH
                sumo_net_path = join(default_path, "6e2fccc4-f09d-411e-93ba-407b6f70c0f9.net.xml")
                sumo_net = sumolib.net.readNet(sumo_net_path, withInternal=True, withLatestPrograms=True)

                # edge_lane = sumo_net.getLane(edgeID_0 + "_" + str(laneIndex_0))
                # edge_lane2 = sumo_net.getLane(edgeID_0 + "_" + str(2))
                # shapes = edge_lane.getShape()


                # raw_shapes2 = edge_lane2.getBoundingBox()
                # point = sumo_net.convertXY2LonLat(raw_shapes[0], raw_shapes[1])
                # point1 = sumo_net.convertXY2LonLat(raw_shapes[2], raw_shapes[3])
                polygons = list()
                if edgeID_0==edgeID_1:
                    if pos_0>pos_1:
                        areaPoints.reverse()
                    edge_lane = sumo_net.getLane(edgeID_0 + "_" + str(laneIndex_0))
                    # shapes = edge_lane.getShape()
                    width=edge_lane.getWidth()
                    # raw_shapes = edge_lane.getBoundingBox(includeJunctions=False)
                    raw_shapes = edge_lane.getShape()
                    for i in range(len(raw_shapes)):
                        upper_left_point = sumo_net.convertXY2LonLat(raw_shapes[0][0], raw_shapes[0][1])
                        if i>0:
                            upper_right_point = sumo_net.convertXY2LonLat(raw_shapes[i][0], raw_shapes[i][1])
                            polygons_i=construction_area_util.construction_area_convert(upper_left_point,upper_right_point,width)
                            if len(polygons)==0:
                                polygons=polygons_i
                            else:
                                # 要插入的元素
                                polygons.insert(i+1,polygons_i[3])
                                polygons.insert(i+1,polygons_i[2])

                                print(polygons)
                                a=1
                    accident['polygons']=polygons
                    print(polygons)
                else:
                    start_edge_lane = sumo_net.getLane(edgeID_0 + "_" + str(laneIndex_0))
                    end_edge_lane = sumo_net.getLane(edgeID_1 + "_" + str(laneIndex_1))
                    start_width = start_edge_lane.getWidth()
                    end_width = end_edge_lane.getWidth()
                    start_raw_shapes = start_edge_lane.getShape()
                    end_raw_shapes = end_edge_lane.getShape()
                    raw_shapes=start_raw_shapes+end_raw_shapes
                    for i in range(len(raw_shapes)):
                        upper_left_point = sumo_net.convertXY2LonLat(raw_shapes[0][0], raw_shapes[0][1])
                        if i>0:
                            upper_right_point = sumo_net.convertXY2LonLat(raw_shapes[i][0], raw_shapes[i][1])
                            polygons_i=construction_area_util.construction_area_convert(upper_left_point,upper_right_point,start_width)
                            if len(polygons)==0:
                                polygons=polygons_i
                            else:
                                # 要插入的元素
                                polygons.insert(i+1,polygons_i[3])
                                polygons.insert(i+1,polygons_i[2])

                                print(polygons)
                                a=1
                    accident['polygons'] = polygons


            else:
                traci.close()
                return JsonResponse.accident_error('施工区未在一个车道上')
        except Exception as e:
            print(str(e))
            traci.close()
            return JsonResponse.accident_error('施工区没在地图上')
    traci.close()
    end1 = time.time()
    print(end1-start1)
    print(rou_cfg)
    return JsonResponse.success(rou_cfg)

@app.errorhandler(Exception)
def error_handler(e):
    """
    全局异常捕获
    """
    return JsonResponse.error(msg=str(e))


def runstart():
    app.run(host='0.0.0.0', port=15002)


def httpserver():
    runstart()



# if __name__ == '__main__':
#     httpserver()
